﻿@using Aspire.Dashboard.Components.Controls.Grid
@using Aspire.Dashboard.Model
@using Aspire.Dashboard.Model.Otlp
@using Aspire.Dashboard.Otlp.Model
@using Aspire.Dashboard.Resources
@using Aspire.Dashboard.Utils
@inject IStringLocalizer<ControlsStrings> Loc
@inject IStringLocalizer<Dialogs> DialogsLoc

<div class="span-details-layout">
    <FluentToolbar Orientation="Orientation.Horizontal">
        <div>
            @((MarkupString)string.Format(ControlsStrings.SpanDetailsResource, ViewModel.Span.Source.Application.ApplicationName))
        </div>
        <FluentDivider Role="DividerRole.Presentation" Orientation="Orientation.Vertical" />
        <div>
            @((MarkupString)string.Format(ControlsStrings.SpanDetailsDuration, DurationFormatter.FormatDuration(ViewModel.Span.Duration)))
        </div>
        <FluentDivider Role="DividerRole.Presentation" Orientation="Orientation.Vertical" />
        <div>
            @((MarkupString)string.Format(ControlsStrings.SpanDetailsStartTime, DurationFormatter.FormatDuration(ViewModel.Span.StartTime - ViewModel.Span.Trace.FirstSpan.StartTime)))
        </div>
        <FluentAnchor slot="end" Appearance="Appearance.Lightweight" Href="@DashboardUrls.StructuredLogsUrl(spanId: ViewModel.Span.SpanId)">@Loc[nameof(ControlsStrings.ViewLogsLink)]</FluentAnchor>
        <FluentDivider slot="end" Role="DividerRole.Presentation" Orientation="Orientation.Vertical" />
        <FluentSearch Placeholder="@Loc[nameof(ControlsStrings.FilterPlaceholder)]"
                      Immediate="true"
                      Autofocus="true"
                      @bind-Value="_filter"
                      slot="end" />
    </FluentToolbar>
    <div class="property-grid-container">
        <FluentAccordion>
            <FluentAccordionItem Heading="@Loc[nameof(ControlsStrings.SpanDetailsSpanHeader)]" Expanded="true">
                <div slot="end">
                    <FluentBadge Appearance="Appearance.Neutral" Circular="true">
                        @FilteredItems.Count()
                    </FluentBadge>
                </div>
                <PropertyGrid TItem="SpanPropertyViewModel"
                              Items="@FilteredItems"
                              GridTemplateColumns="1fr 2fr"
                              NameColumnValue="(vm) => vm.Name"
                              ValueColumnValue="(vm) => vm.Value"
                              NameSort="_nameSort"
                              ValueSort="_valueSort"
                              HighlightText="@_filter" />
            </FluentAccordionItem>
            <FluentAccordionItem Heading="@Loc[nameof(ControlsStrings.SpanDetailsContextHeader)]" Expanded="true">
                <div slot="end">
                    <FluentBadge Appearance="Appearance.Neutral" Circular="true">
                        @FilteredContextItems.Count()
                    </FluentBadge>
                </div>
                <PropertyGrid TItem="SpanPropertyViewModel"
                              Items="@FilteredContextItems"
                              GridTemplateColumns="1fr 2fr"
                              NameColumnValue="(vm) => vm.Name"
                              ValueColumnValue="(vm) => vm.Value"
                              NameSort="_nameSort"
                              ValueSort="_valueSort"
                              HighlightText="@_filter" />
            </FluentAccordionItem>
            <FluentAccordionItem Heading="@Loc[nameof(ControlsStrings.SpanDetailsResourceHeader)]" Expanded="true">
                <div slot="end">
                    <FluentBadge Appearance="Appearance.Neutral" Circular="true">
                        @FilteredResourceItems.Count()
                    </FluentBadge>
                </div>
                <PropertyGrid TItem="SpanPropertyViewModel"
                              Items="@FilteredResourceItems"
                              GridTemplateColumns="1fr 2fr"
                              NameColumnValue="(vm) => vm.Name"
                              ValueColumnValue="(vm) => vm.Value"
                              NameSort="_nameSort"
                              ValueSort="_valueSort"
                              HighlightText="@_filter" />
            </FluentAccordionItem>
            <FluentAccordionItem Heading="@Loc[nameof(ControlsStrings.SpanDetailsEventsHeader)]" Expanded="true">
                <div slot="end">
                    <FluentBadge Appearance="Appearance.Neutral" Circular="true">
                        @FilteredSpanEvents.Count()
                    </FluentBadge>
                </div>
                <PropertyGrid TItem="OtlpSpanEvent"
                              Items="@FilteredSpanEvents"
                              GridTemplateColumns="1fr 2fr"
                              NameColumnValue="(vm) => DurationFormatter.FormatDuration(vm.TimeOffset(ViewModel.Span))"
                              NameColumnTitle="@(Loc[nameof(ControlsStrings.TimeOffsetColumnHeader)])"
                              ValueColumnValue="(vm) => vm.Name"
                              ValueColumnTitle="@(Loc[nameof(ControlsStrings.EventColumnHeader)])"
                              IsNameSortable="false"
                              IsValueSortable="false"
                              HighlightText="@_filter">
                    <ExtraValueContent>
                        @if (context.Attributes.Length > 0)
                        {
                            // There's a weird bug where trying to render a nested FluentDataGrid here with a non-primitive
                            // TItem leads to the click event not being raised *only in the value (not header) rows*. A
                            // workaround is to use the attribute index as the item and query the attributes list for its
                            // name and value in the name/value producers.
                            <PropertyGrid TItem="int"
                                          Items="@context.Attributes.Select((_, i) => i).AsQueryable()"
                                          GridTemplateColumns="1fr 2fr"
                                          NameColumnValue="(i) => context.Attributes[i].Key"
                                          ValueColumnValue="(i) => context.Attributes[i].Value"
                                          IsNameSortable="false"
                                          IsValueSortable="false"
                                          GenerateHeader="GenerateHeaderOption.Default" />
                        }
                    </ExtraValueContent>
                </PropertyGrid>
            </FluentAccordionItem>
            <FluentAccordionItem Heading="@Loc[nameof(ControlsStrings.SpanDetailsLinksHeader)]" Expanded="true">
                <div slot="end">
                    <FluentBadge Appearance="Appearance.Neutral" Circular="true">
                        @FilteredSpanLinks.Count()
                    </FluentBadge>
                </div>
                <FluentDataGrid ResizeLabel="@AspireFluentDataGridHeaderCell.GetResizeLabel(Loc)"
                                ResizeType="DataGridResizeType.Discrete"
                                TGridItem="SpanLinkViewModel"
                                Items="@FilteredSpanLinks"
                                Style="width:100%"
                                GenerateHeader="GenerateHeaderOption.Sticky"
                                GridTemplateColumns="4fr 1fr"
                                ShowHover="true">
                    <AspireTemplateColumn Title="@Loc[nameof(ControlsStrings.SpanDetailsSpanColumnHeader)]">
                        @WriteSpanLink(context)
                    </AspireTemplateColumn>
                    <AspireTemplateColumn Title="@Loc[nameof(ControlsStrings.SpanDetailsDetailsColumnHeader)]">
                        <FluentButton Appearance="Appearance.Lightweight" OnClick="@(() => OnViewDetailsAsync(context))">@Loc[nameof(ControlsStrings.ViewAction)]</FluentButton>
                    </AspireTemplateColumn>
                </FluentDataGrid>
            </FluentAccordionItem>
            <FluentAccordionItem Heading="@Loc[nameof(ControlsStrings.SpanDetailsBacklinksHeader)]" Expanded="true">
                <div slot="end">
                    <FluentBadge Appearance="Appearance.Neutral" Circular="true">
                        @FilteredSpanBacklinks.Count()
                    </FluentBadge>
                </div>
                <FluentDataGrid ResizeLabel="@AspireFluentDataGridHeaderCell.GetResizeLabel(Loc)"
                                ResizeType="DataGridResizeType.Discrete"
                                TGridItem="SpanLinkViewModel"
                                Items="@FilteredSpanBacklinks"
                                Style="width:100%"
                                GenerateHeader="GenerateHeaderOption.Sticky"
                                GridTemplateColumns="4fr 1fr"
                                ShowHover="true">
                    <AspireTemplateColumn Title="@Loc[nameof(ControlsStrings.SpanDetailsSpanColumnHeader)]">
                        @WriteSpanLink(context)
                    </AspireTemplateColumn>
                    <AspireTemplateColumn Title="@Loc[nameof(ControlsStrings.SpanDetailsDetailsColumnHeader)]">
                        <FluentButton Appearance="Appearance.Lightweight" OnClick="@(() => OnViewDetailsAsync(context))">@Loc[nameof(ControlsStrings.ViewAction)]</FluentButton>
                    </AspireTemplateColumn>
                </FluentDataGrid>
            </FluentAccordionItem>
        </FluentAccordion>
    </div>
</div>

@code {
    RenderFragment WriteSpanLink(SpanLinkViewModel context)
    {
        var content = context.Span != null
            ? SpanWaterfallViewModel.GetTitle(context.Span, ViewModel.Applications)
            : $"{Loc[nameof(ControlsStrings.SpanDetailsSpanPrefix)]}: {OtlpHelpers.ToShortenedId(context.SpanId)}";
        var color = context.Span != null
            ? ColorGenerator.Instance.GetColorHexByKey(OtlpApplication.GetResourceName(context.Span.Source, ViewModel.Applications))
            : "transparent";

        return @<div>
        <div class="spanlink-container" style="height:32px;">
            <span class="spanlink-text" title="@content" style="padding-left:5px; border-left-width: 5px; border-left-style: solid; border-left-color: @(color);">
                @content
            </span>
        </div>
        @if (context.Attributes.Length > 0)
        {
            // There's a weird bug where trying to render a nested FluentDataGrid here with a non-primitive
            // TItem leads to the click event not being raised *only in the value (not header) rows*. A
            // workaround is to use the attribute index as the item and query the attributes list for its
            // name and value in the name/value producers.
            <PropertyGrid TItem="int"
                          Items="@context.Attributes.Select((_, i) => i).AsQueryable()"
                          GridTemplateColumns="1fr 2fr"
                          NameColumnValue="(i) => context.Attributes[i].Key"
                          ValueColumnValue="(i) => context.Attributes[i].Value"
                          IsNameSortable="false"
                          IsValueSortable="false"
                          GenerateHeader="GenerateHeaderOption.Default" />
        }
    </div>;
    }
}
